#ifndef DSPSIMULATOR_SEGMENT_H
#define DSPSIMULATOR_SEGMENT_H

#include <vector>
#include <bitset>
#include <simulator/memory/segmentKind.h>
#include <simulator/type/type.h>


/**
 *  ELF文件段
 */
class Segment {
private:
    u64 m_index;
    // 段类型
    SegmentKind m_segmentKind;
    // 段的权限，执行
    bool X;
    // 段的权限，写
    bool W;
    // 段的权限，读
    bool R;
    // 段加载到内存中的大小，字节为单位
    u64 m_memSize;
    // 段加载到内存中的起始地址
    u64 m_addrBegin;
    // 段中的字节数据
    std::vector<u8> m_data;
public:

    /**
     * 段的有参构造器
     * @param index 段在elf文件中的编号
     * @param addrBegin 段的起始地址
     * @param memSize 段在内存中的大小
     * @param data 段的数据
     * @param fileSize 段在elf文件中的大小
     * @param canRead 读权限
     * @param canWrite 写权限
     * @param canExecute 执行权限
     * @param segmentKind 段类型
     */
    Segment(u64 index, u64 addrBegin, u64 memSize, const u8 data[], u64 fileSize, bool canRead, bool canWrite,
            bool canExecute,
            SegmentKind segmentKind = SegmentKind::UnKnown);

    Segment(const Segment &);

    ~Segment() = default;

    /**
     * 在段偏移为offset处写入size个字节，字节数据为data
     * @param offset  写入数据的起始字节的偏移量
     * @param size    写入数据的大小，以字节为单位
     * @param data    写入的数据
     */
    void write(u64 offset, u64 size, const u8 data[]);

    void write(u64 offset, u64 size, const std::vector<u8> &data);

    /**
     * 在段偏移为offset处读出N个字节
     * @param offset
     * @param N
     * @return 读出的N个字节
     */
    std::vector<u8> readNBytes(u64 offset, u64 N);

    /**
     * 判断当前段是否可读
     * @return
     */
    bool canRead() const;

    /**
     * 判断当前段是否可写
     * @return
     */
    bool canWrite() const;

    /**
     * 判断当前段是否可执行
     * @return
     */
    bool canExecute() const;

    /**
     * 获取当前段在内存中加载的大小
     * @return
     */
    u64 getSegmentSize() const;

    /**
     * 获取当前段在内存中加载的起始地址
     * @return
     */
    u64 getAddressBegin() const;

    void printSegmentInfo() const;
};


#endif //DSPSIMULATOR_SEGMENT_H
